home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 2 / Atari Mega Archive CD - Volume 2.iso / minix / up1510b.tgz / up1510b / src / commands / mkfs.c < prev    next >
C/C++ Source or Header  |  1990-07-23  |  28KB  |  1,221 lines

  1. /* mkfs  -  make the MINIX filesystem    Authors: A. Tanenbaum & P. Ogilvie */
  2.  
  3.  
  4. /*         Andy Tanenbaum & Paul Ogilvie, June 1986
  5.  *
  6.  *    This program was initially designed to build a filesystem
  7.  *    with blocksize = zonesize. During the course of time the
  8.  *    program is being converted to handle zone_size > blocksize
  9.  *    but this isn't complete yet. Where routines can handle the
  10.  *    situation this is mentioned in the comment.
  11.  *
  12.  *    To compile this program for MS-DOS, use: cc -DDOS mkfs.c diskio.asm
  13.  *    To compile this program for UNIX,   use: cc -DUNIX mkfs.c
  14.  *    To compile this program for MINIX,  use: cc mkfs.c
  15.  */
  16.  
  17. #include <sys/types.h>
  18. #include <limits.h>
  19. #include <minix/config.h>
  20. #include <minix/const.h>
  21. #include <minix/type.h>
  22. #include "../fs/const.h"
  23.  
  24. #undef EXTERN
  25. #define EXTERN            /* get rid of EXTERN by making it null */
  26. #include "../fs/type.h"
  27. #include "../fs/super.h"
  28.  
  29. #include <fcntl.h>
  30. #include <sys/stat.h>
  31. #include <unistd.h>
  32. #include <stdlib.h>
  33. #include <stdio.h>
  34.  
  35. #ifndef DOS
  36. #ifndef UNIX
  37. #undef printf            /* printf is a macro for printk */
  38. #define UNIX
  39. #endif
  40. #endif
  41.  
  42.  
  43.  
  44. #define INODE_MAP            2
  45. #define MAX_TOKENS          10
  46. #define LINE_LEN           200
  47. #define BIN                  2
  48. #define BINGRP               2
  49. #define BIT_MAP_SHIFT       13
  50. #define N_BLOCKS       0x10000L    /* must be multiple of 8 */
  51.  
  52. #ifdef DOS
  53.    maybedefine O_RDONLY         4    /* O_RDONLY | BINARY_BIT */
  54.    maybedefine BWRITE         5    /* O_WRONLY | BINARY_BIT */
  55. #endif
  56.  
  57. #if (MACHINE == ATARI)
  58. int    isdev;
  59. #endif
  60.  
  61. int next_zone, next_inode, zone_size, zone_shift = 0, zoff;
  62. unsigned nrblocks;
  63. int inode_offset, nrinodes, lct = 1, disk, fd, print = 0, file = 0;
  64. int override = 0, simple = 0, dflag;
  65. int donttest;            /* skip test if it fits on medium */
  66.  
  67. long current_time, bin_time;
  68. char zero[BLOCK_SIZE], *lastp;
  69. char umap[(N_BLOCKS + 8) / 8];    /* bit map tells if block read yet */
  70. int zone_map = 3;        /* where is zone map? (depends on # inodes) */
  71.  
  72. FILE *proto;
  73. char gwarning[] = {65, 46, 83, 46, 84, 97, 110, 101, 110, 98, 97, 117, 109, 10};
  74.  
  75.  
  76.  
  77. /*================================================================
  78.  *                    mkfs  -  make filesystem
  79.  *===============================================================*/
  80.  
  81. main(argc, argv)
  82. int argc;
  83. char *argv[];
  84. {
  85.   int i, mode, usrid, grpid, badusage = 0;
  86.   unsigned zones, inodes;
  87.   unsigned long blocks;
  88.   char *token[MAX_TOKENS], line[LINE_LEN];
  89.   FILE *fopen();
  90.   long time(), ls;
  91.   struct stat statbuf;
  92.  
  93.  
  94.   /* Get two times, the current time and the mod time of the binary of
  95.    * mkfs itself.  When the -d flag is used, the later time is put into
  96.    * the i_mtimes of all the files.  This feature is useful when
  97.    * producing a set of file systems, and one wants all the times to be
  98.    * identical. First you set the time of the mkfs binary to what you
  99.    * want, then go. */
  100.   current_time = time(0L);    /* time mkfs is being run */
  101.   stat(argv[0], &statbuf);
  102.   bin_time = statbuf.st_mtime;    /* time when mkfs binary was last modified */
  103.  
  104.   /* Process parameters and switches */
  105.   if (argc != 3 && argc != 4) badusage = 1;
  106.   if (stat(argv[argc - 1], &statbuf) == 0) {
  107.     if ((statbuf.st_mode & S_IFMT) != S_IFREG) badusage = 1;
  108.   }
  109.   if (badusage) {
  110.     write(2, "Usage: mkfs [-ldt] special proto\n", 33);
  111.     exit(1);
  112.   }
  113.   while (--argc) {
  114.     switch (argv[argc][0]) {
  115.         case '-':
  116.         while (*++argv[argc]) switch (*argv[argc]) {
  117.                 case 'l':
  118.                 case 'L':    print = 1;    break;
  119.                 case 'o':
  120.                 case 'O':
  121.                 override = 1;
  122.                 break;
  123.                 case 'd':
  124.                 case 'D':
  125.                 current_time = bin_time;
  126.                 dflag = 1;
  127.                 break;
  128.                 case 't':
  129.                 case 'T':
  130.                 donttest = 1;
  131.                 break;
  132.                 default:
  133.                 printf("Bad switch %c, ignored.\n", *argv[argc]);
  134.             }
  135.         break;
  136.  
  137.         default:
  138.  
  139.         /* Process proto & special */
  140.         proto = fopen(argv[argc], "r");
  141.         if (proto != (FILE *) NULL) {
  142.             /* Prototype file is readable. */
  143.             getline(line, token);    /* skip boot block info. */
  144.  
  145.             /* Read the line with the block and inode counts. */
  146.             getline(line, token);
  147.             blocks = atol(token[0]);
  148.             if (blocks > N_BLOCKS)
  149.                 pexit("Block count too large");
  150.             inodes = atoi(token[1]);
  151.  
  152.             /* Process mode line for root directory. */
  153.             getline(line, token);
  154.             mode = mode_con(token[0]);
  155.             usrid = atoi(token[1]);
  156.             grpid = atoi(token[2]);
  157.  
  158.         } else {
  159.  
  160.             /* Maybe the prototype file is just a size.
  161.              * Check for that. */
  162.             blocks = atol(argv[argc]);
  163.             if (blocks < 4) pexit("Can't open prototype file");
  164.             if (blocks > N_BLOCKS)
  165.                 pexit("Block count too large");
  166.  
  167.             /* Ok, make simple file system of given size,
  168.              * using defaults. */
  169.             inodes = (blocks / 3) + 8;    /* default is 3
  170.                              * blocks/file */
  171.             mode = 040777;
  172.             usrid = BIN;
  173.             grpid = BINGRP;
  174.             simple = 1;
  175.         }
  176.  
  177.         /* Open special */
  178.         argc--;
  179.         special(argv[argc]);
  180.  
  181.         nrblocks = blocks;
  182.         nrinodes = inodes;
  183.     }            /* end switch */
  184.   }                /* end while */
  185.  
  186.  
  187.  
  188. #ifdef UNIX
  189.   if (!donttest) {
  190.     static short testb[BLOCK_SIZE / sizeof(short)];
  191.  
  192.     /* Try writing the last block of partition or diskette. */
  193.     ls = lseek(fd, ((long) blocks - 1L) * BLOCK_SIZE, SEEK_SET);
  194.     testb[0] = 0x3245;
  195.     testb[1] = 0x11FF;
  196.     if (write(fd, (char *) testb, BLOCK_SIZE) != BLOCK_SIZE)
  197.         pexit("File system is too big for minor device");
  198.     sync();            /* flush write, so if error next read fails */
  199.     lseek(fd, ((long) blocks - 1L) * BLOCK_SIZE, SEEK_SET);
  200.     testb[0] = 0;
  201.     testb[1] = 0;
  202.     i = read(fd, (char *) testb, BLOCK_SIZE);
  203.     if (i != BLOCK_SIZE || testb[0] != 0x3245 || testb[1] != 0x11FF)
  204.         pexit("File system is too big for minor device");
  205.     lseek(fd, ((long) blocks - 1L) * BLOCK_SIZE, SEEK_SET);
  206.     testb[0] = 0;
  207.     testb[1] = 0;
  208.     if (write(fd, (char *) testb, BLOCK_SIZE) != BLOCK_SIZE)
  209.         pexit("File system is too big for minor device");
  210.     lseek(fd, 0L, SEEK_SET);
  211.   }
  212. #endif
  213.  
  214.   /* Make the file-system */
  215.  
  216.   cache_init();
  217. #if (MACHINE == ATARI)
  218.   if (isdev) {
  219.     char block0[BLOCK_SIZE];
  220.     get_block(0, block0);    
  221.     /* need to read twice; first time gets an empty block */
  222.     get_block(0, block0);
  223.     /* zero parts of the boot block so the disk won't be recognized as
  224.        a tos disk any more. */
  225.     block0[0] = block0[1] = 0;    /* branch code to boot code    */
  226.     strncpy(&block0[2], "MINIX ", 6);
  227.     block0[16] = 0;        /* number of FATS              */
  228.     block0[17] = block0[18] = 0;/* number of dir entries       */
  229.     block0[22] = block0[23] = 0;/* sectors/FAT                 */
  230.     bzero(&block0[30], 480);    /* boot code                   */
  231.     put_block(0, block0);    
  232.   }
  233.   else
  234. #endif
  235.   put_block(0, zero);        /* Write a null boot block. */
  236.  
  237.   zone_shift = 0;        /* for future use */
  238.   zones = nrblocks >> zone_shift;
  239.  
  240.   super(zones, inodes);
  241.  
  242.   i = alloc_inode(mode, usrid, grpid);
  243.   rootdir(i);
  244.   if (simple == 0) eat_dir(i);
  245.  
  246.   if (print) print_fs();
  247.   flush();
  248.   exit(0);
  249.  
  250.  
  251. }                /* end main */
  252.  
  253.  
  254.  
  255.  
  256. /*================================================================
  257.  *                 super  -  construct a superblock
  258.  *===============================================================*/
  259.  
  260. super(zones, inodes)
  261. unsigned zones, inodes;
  262. {
  263.  
  264.   unsigned int i, inodeblks, initblks, initzones, nrzones;
  265.   unsigned int bit_map_len, b_needed, b_allocated, residual;
  266.   long zo;
  267.   struct super_block *sup;
  268.   char buf[BLOCK_SIZE], *cp;
  269.  
  270.   sup = (struct super_block *) buf;
  271.  
  272.   sup->s_ninodes = inodes;
  273.   sup->s_nzones = zones;
  274.   sup->s_imap_blocks = bitmapsize(1 + inodes);
  275.   sup->s_zmap_blocks = bitmapsize(zones);
  276.   inode_offset = sup->s_imap_blocks + sup->s_zmap_blocks + 2;
  277.   inodeblks = (inodes + INODES_PER_BLOCK - 1) / INODES_PER_BLOCK;
  278.   initblks = inode_offset + inodeblks;
  279.   initzones = (initblks + (1 << zone_shift) - 1) >> zone_shift;
  280.   nrzones = nrblocks >> zone_shift;
  281.   sup->s_firstdatazone = (initblks + (1 << zone_shift) - 1) >> zone_shift;
  282.   zoff = sup->s_firstdatazone - 1;
  283.   sup->s_log_zone_size = zone_shift;
  284.   sup->s_magic = SUPER_MAGIC;    /* identify super blocks */
  285.   zo = 7L + (long) NR_INDIRECTS
  286.     + (long) NR_INDIRECTS *NR_INDIRECTS;
  287.   sup->s_max_size = zo * BLOCK_SIZE;
  288.   zone_size = 1 << zone_shift;    /* nr of blocks per zone */
  289.  
  290.   for (cp = buf + sizeof(*sup); cp < &buf[BLOCK_SIZE]; cp++) *cp = 0;
  291.   put_block(1, buf);
  292.  
  293.   /* Clear maps and inodes. */
  294.   fo